﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace DienLib.SummitLib
{
    /// <summary>
    /// Wrapper for Infragistics UltraTreeNode in Summit Main Form
    /// </summary>
    public class UltraTreeNode
    {
        private object _refobj;
        private Control _reftree;
        private TreeNodesCollection _nodes;

        public UltraTreeNode(object refUltraTreeNode, Control refUltraTreeView)
        {
            _refobj = refUltraTreeNode;
            _reftree = refUltraTreeView;

            // Nodes is a property of _refobj so can declare a private _nodes & use parrallel with _refobj
            if (_reftree.InvokeRequired) _nodes = new TreeNodesCollection(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.GetProperty<object>(_refobj, "Nodes"); }), _reftree);
            else _nodes = new TreeNodesCollection(DienLib.Reflector.GetProperty<object>(_refobj, "Nodes"), _reftree); // Does it really need Invoke ?

            //MessageBox.Show("_nodes inside UltraTreeNode : " + _refobj.ToString() + "are : " + _nodes.ToString());
        }

        /// <summary>
        /// Return the Original Wrapped Object for this Wrapper
        /// </summary>
        public object Wrappee
        {
            get
            {
                return _refobj;
            }
        }

        public bool Expanded
        {
            get
            {
                if (_reftree.InvokeRequired) return (bool)_reftree.Invoke((Func<bool>)delegate { return DienLib.Reflector.GetProperty<bool>(_refobj, "Expanded"); });
                else return DienLib.Reflector.GetProperty<bool>(_refobj, "Expanded");
            }
            set
            {
                if (_reftree.InvokeRequired) _reftree.Invoke((MethodInvoker)delegate { DienLib.Reflector.SetProperty<bool>(_refobj, "Expanded", value); });
                else DienLib.Reflector.SetProperty<bool>(_refobj, "Expanded", value);
            }
        }

        public string Text
        {
            get
            {
                if (_reftree.InvokeRequired) return (string)_reftree.Invoke((Func<string>)delegate { return DienLib.Reflector.GetProperty<string>(_refobj, "Text"); });
                else return DienLib.Reflector.GetProperty<string>(_refobj, "Text");
            }
        }

        public string FullPath
        {
            get
            {
                if (_reftree.InvokeRequired) return (string)_reftree.Invoke((Func<string>)delegate { return DienLib.Reflector.GetProperty<string>(_refobj, "FullPath"); });
                else return DienLib.Reflector.GetProperty<string>(_refobj, "FullPath");
            }
        }

        public bool Selected
        {
            get
            {
                if (_reftree.InvokeRequired) return (bool)_reftree.Invoke((Func<bool>)delegate { return DienLib.Reflector.GetProperty<bool>(_refobj, "Selected"); });
                else return DienLib.Reflector.GetProperty<bool>(_refobj, "Selected");
            }
            set
            {
                if (_reftree.InvokeRequired) _reftree.Invoke((MethodInvoker)delegate { DienLib.Reflector.SetProperty<bool>(_refobj, "Selected", value); });
                else DienLib.Reflector.SetProperty<bool>(_refobj, "Selected", value);
            }
        }

        public TreeNodesCollection Nodes
        {
            get
            {
                return _nodes;
                // No need to call Reflector everytime because Nodes is a property of _refobj. Use a private var instead.
                //if (_refobj.InvokeRequired) return new TreeNodesCollection(_refobj.Invoke((Func<object>)delegate { return DienLib.Reflector.GetProperty<object>(_refobj, "Nodes"); }), _refobj);
                //else return new TreeNodesCollection(DienLib.Reflector.GetProperty<object>(_refobj, "Nodes"), _refobj); // Does it really need Invoke ?
            }
        }

        /// <summary>
        /// return object as Infragistic.Win.UIElement
        /// </summary>
        public UIElement UIElement
        {
            get
            {
                if (_reftree.InvokeRequired) return new UIElement(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.GetProperty<object>(_refobj, "UIElement"); }), _reftree);
                else return new UIElement(DienLib.Reflector.GetProperty<object>(_refobj, "UIElement"), _reftree);
            }
        }

        #region DISPOSE METHOD
        // Dispose() calls Dispose(true)
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // NOTE: Leave out the finalizer altogether if this class doesn't 
        // own unmanaged resources itself, but leave the other methods
        // exactly as they are. 
        ~UltraTreeNode()
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }

        // The bulk of the clean-up code is implemented in Dispose(bool)
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources, (detach event ?)
                if (this._refobj != null) this._refobj = null; // Khong keu this._refobj.Dispose vi Reference toi object do. Ngoai ra do pass reference nen this._refobj = null khong anh huong gi toi object goc
                if (this._reftree != null) this._reftree = null;
                if (this._nodes != null) this._nodes = null;
            }

            /* free native resources if there are any.
            if (nativeResource != IntPtr.Zero) 
            {
                Marshal.FreeHGlobal(nativeResource);
                nativeResource = IntPtr.Zero;
            }*/
        }
        #endregion
    }
}